
import java.io.BufferedWriter;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;


public class Main {
    
    private final static String IntegerInputFilename = "phw_input.txt";
    private final static int NumberOfIntegersInFile = 10;
    private final static Random random = new Random();
    private final static int N = 100;
    private final static String OutputFilename = "trentonnall_phw_output.txt";
    
    public static void main(String[] args) {
        System.out.println("This is a test of the main method...");
        System.out.println();
        
        runFileInputTest();
        
        runRandomArrayGenerationTest();
    }
    
    public static void runFileInputTest() {
        // read array of integers from file
        int[] inputArray = readIntegersFromFile();
        
        // read file of integers
        int algorithm1Answer = Algorithms.Algorithm1(inputArray, 1, inputArray.length);
        int algorithm2Answer = Algorithms.Algorithm2(inputArray, 1, inputArray.length);
        int algorithm3Answer = Algorithms.Algorithm3(inputArray, 1, inputArray.length);
        
        System.out.printf("\n\nalgorithm-1: %d; algorithm-2: %d; algorithm-3: %d\n\n",
                algorithm1Answer, algorithm2Answer, algorithm3Answer);
    }

    private static int[] readIntegersFromFile() {
        try {
            // attempt to read integers from file
            int[] result = new int[NumberOfIntegersInFile];
            
            File inputFile = new File(IntegerInputFilename);
            Scanner scanner = new Scanner(inputFile).useDelimiter(",");
            
            for (int i = 0; i < NumberOfIntegersInFile; i++) {
                result[i] = scanner.nextInt();
            }
            
            return result;
        }
        catch (Exception e) {
            System.out.println("\n\nFatal error attempting to read: " + IntegerInputFilename
                    + "\nError: " + e.toString() + "\n\n");
            
            System.exit(-1);
        }
        
        return null;
    }

    private static void runRandomArrayGenerationTest() {
        // create structure to hold arrays of random integers
        List<int[]> arrays = new ArrayList<int[]>();
        
        // create 19 arrays of random integers of specified sizes
        for (int i = 0, size = 10; i < 19; i++, size += 5) {
            int[] array = new int[size];
            randomFillArray(array);
            arrays.add(array);
        }
        
        int[][] results = new int[19][6];
        
        
        // run evaluations for algorithm 1
        int rowIndex = 0;
        for (int[] array : arrays) {
            long t1 = System.nanoTime();
            
            for (int i = 0; i < N; i++) {
                Algorithms.Algorithm1(array, 1, array.length);
            }
            
            long timeDiff = System.nanoTime() - t1;
            results[rowIndex++][0] = (int)Math.ceil(timeDiff / N);
        }
        
        
        // run evaluations for algorithm 2
        rowIndex = 0;
        for (int[] array : arrays) {
            long t1 = System.nanoTime();
            
            for (int i = 0; i < N; i++) {
                Algorithms.Algorithm2(array, 1, array.length);
            }
            
            long timeDiff = System.nanoTime() - t1;
            results[rowIndex++][1] = (int)Math.ceil(timeDiff / N);
        }
        
        
        // run evaluations for algorithm 3
        rowIndex = 0;
        for (int[] array : arrays) {
            long t1 = System.nanoTime();
            
            for (int i = 0; i < N; i++) {
                Algorithms.Algorithm3(array, 1, array.length);
            }
            
            long timeDiff = System.nanoTime() - t1;
            results[rowIndex++][2] = (int)Math.ceil(timeDiff / N);
        }
        
        // fill results with calculated T(n) values here - should fill
        // last three columns
        // you may need to scale here?
        
        // write results to a text file
        writeResultToOutputFile(results);
    }
    
    private static void randomFillArray(int[] array) {
        for (int i =0; i < array.length; i++) {
            array[i] = getRandom();
        }
    }
    
    private static int getRandom() {
        // generates integers from 0+ (inclusive)
        int randomNumber = random.nextInt();
        
        // integer has 50% of being negative
        if (randomNumber != 0) {
            if (Math.random() < .5) {
                randomNumber = -randomNumber;
            }
        }
        
        return randomNumber;
    }

    private static void writeResultToOutputFile(int[][] results) {
        try {
            BufferedWriter writer =
                    Files.newBufferedWriter(Paths.get(OutputFilename), StandardCharsets.UTF_8);
            
            writer.write("algorithm-1,algorithm-2,algorithm-3,T1(stuff),T2(stuff),T3(stuff)");
            writer.newLine();
            
            for (int row = 0; row < results.length; row++) {
                for (int column = 0; column < 6; column++) {
                    if (column != 0) {
                        writer.write(",");
                    }
                    writer.write(results[row][column]);
                }
                
                writer.newLine();
            }
            
            writer.close();
        } catch (Exception e) {
            System.out.println("\n\nError writing file: " + OutputFilename
                    + "\nPlease verify that there are no I/O or configuration problems...\n"
                    + "Error: " + e.toString() + "\n\n");
        }
    }
}
